package com.sailing.study.clickhouse;

import java.util.Arrays;
import java.util.List;

/**
 * @author chenchao
 * @time 2024-08-12 10:12
 */
public class MysqlToClickHouse {

    public static String convertMysqlTableDDLToClickHouse(String tableDDL) {
        String tables = tableDDL;
        String[] rows = tables.split("\n");
        String replaceTables = "";
        int i = 0;
        for (String row : rows) {
            if (row.contains("KEY")) {
                continue;
            }
            if (row.contains(") ENGINE=InnoDB")) {
                row = ") ENGINE = MergeTree";
            }
            String changeRow = row.replaceAll(" NOT NULL", "")
                    .replaceAll("DEFAULT NULL", "")
                    .replaceAll("DEFAULT ''", "")
                    .replaceAll("DEFAULT '-?\\d+'", "")
                    .replaceAll("DEFAULT CURRENT_TIMESTAMP", "")
                    .replaceAll("AUTO_INCREMENT", "")
                    .replaceAll("CHARACTER SET utf8mb4", "")
                    .replaceAll("CHARACTER SET utf8", "")
                    .replaceAll("ON UPDATE CURRENT_TIMESTAMP", "")
                    .replaceAll("CURRENT_TIMESTAMP", "")

                    .replaceAll("datetime DEFAULT NULL", "DateTime")
                    .replaceAll(" timestamp ", " DateTime ")
                    .replaceAll(" datetime ", " DateTime ");

            //convert String
            changeRow = changeRow.replaceAll("varchar\\(\\d+\\) DEFAULT NULL", "Nullable(String)");
            changeRow = changeRow.replaceAll("varchar\\(\\d+\\)", "String");
            changeRow = changeRow.replaceAll("text", "String");

            String[] changeColumns = changeRow.split("[ ]");

            //      System.out.println(changeRow);
            if (matchNumber(changeColumns[3])) {
                changeRow = convertNumber(changeRow, changeColumns[3]);
            }

            changeRow.replaceAll(" Null ", "");

            replaceTables += changeRow + "\n";
            i++;
        }
        if (replaceTables.contains(",) ENGINE = MergeTree")) {
            String temp = replaceTables.substring(0, replaceTables.indexOf(",) ENGINE = MergeTree"));
            replaceTables = temp + ") ENGINE = MergeTree \n" +
                    " PARTITION BY intDiv(id,18446744073709551)\n" +
                    "PRIMARY KEY id\n" +
                    "ORDER BY id\n" +
                    "SETTINGS index_granularity = 8192";
        }
//        replaceTables.replaceAll("CREATE TABLE `" + tableDDL + "`", tableDDL + "_local");

        return replaceTables;
    }

    static List<String> mysqlNumberTypes = Arrays.asList("tinyint", "smallint", "bigint", "int");

    static boolean matchNumber(String fullType) {
        for (String type : mysqlNumberTypes) {
            if (fullType.contains(type)) {
                return true;
            }
        }
        return false;
    }

    static String findNumberType(String fullType) {

        for (String type : mysqlNumberTypes) {
            if (fullType.contains(type)) {
                return type;
            }
        }

        return "int";
    }


    static String getNumberDecimal(String numberClare) {
        return numberClare
                .replaceAll("bigint", "")
                .replaceAll("tinyint", "")
                .replaceAll("smallint", "")
                .replaceAll("int", "")
                .replaceAll("\\(", "")
                .replaceAll("\\)", "");
    }


    static String convertNumber(String changeRow, String numberCol) {
        String numberDecimal = getNumberDecimal(numberCol);
        int length = numberDecimal != null && numberDecimal.trim().length() > 0 ? Integer.parseInt(numberDecimal) : 0;
        String type = findNumberType(numberCol);
        if (length == 0) {

            if (type.equals("tinyint")) {
                changeRow = changeRow.replaceFirst(type, "Int8");
            } else if (type.equals("smallint")) {
                changeRow = changeRow.replaceFirst(type, "Int16");
            } else if (type.equals("int")) {
                changeRow = changeRow.replaceFirst(type, "Int32");
            } else if (type.equals("bigint")) {
                changeRow = changeRow.replaceFirst(type, "Int64");
            }
            return changeRow;
        }
        if (length < 3) {
            changeRow = changeRow.replaceFirst(type + "\\(" + length + "\\)", "Int8");
        } else if (length < 5) {
            changeRow = changeRow.replaceFirst(type + "\\(" + length + "\\)", "Int16");
        } else if (length <= 9) {
            changeRow = changeRow.replaceFirst(type + "\\(" + length + "\\)", "Int32");
        } else {
            changeRow = changeRow.replaceFirst(type + "\\(" + length + "\\)", "Int64");
        }
        return changeRow;
    }
}
